﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
using IBNet.UtilsDataStructuresAndExtensions;

namespace IBNet.LongTermTrade
{
   public partial class LongTermTradeMainForm : Form, IWrapLongTermTradeMainForm
   {
      const int DesiredPositionSizeInDollars = 12000;
      const decimal LongOpeningOrderLimitPricePercentage = 1.03m;
      const decimal ShortOpeningOrderLimitPricePercentage = 0.97m;
      const decimal LongTargetPercentage = 1.05m;
      const decimal ShortTargetPercentage = 0.95m;
      const decimal TrailingPercentage = 0.04m;
      const int MaximumLengthOfTradeInDays = 13;

      IBClient client = new IBClient();
      IWrapLongTermTradeMainForm ClientWrappers;

      bool Connected { get { return client.Connected; } }

      HashSet<int> _openingOrderIds = new HashSet<int>();
      Dictionary<int, OrderAndContract> _orderIdToOrderAndContract = new Dictionary<int, OrderAndContract>();
      Dictionary<int, string> _requestIdForMarketDataToSymbol = new Dictionary<int, string>();
      Dictionary<int, decimal> _marketDataRequestIdToClosingPrice = new Dictionary<int, decimal>();

      AutoResetEvent _closingPriceReceivedOrSymbolNotFound = new AutoResetEvent(false);

      // IB treats submitting an order Id lower than an order Id already submitted
      // as an error. This lock enforces this constraint by preventing
      // a race condition that could allow an order Id to be submitted that is lower
      // than an order Id already submitted.
      readonly object _onlySubmitStrictlyIncreasingOrderIdsLock = new object();

      int _currentOrderId;
      int _currentRequestId;
      bool _areDisconnected;

      volatile bool _symbolFoundWhenRequestingClosingPrice;

      public LongTermTradeMainForm()
      {
         InitializeComponent();
         client.Event_ErrorOccurred.AttachEventHandler(client_ErrorOccurred);
         client.Event_NextValidOrderIdReceived.AttachEventHandler(client_NextValidOrderIdReceived);
         client.Event_ExecutionDetailsReceived.AttachEventHandler(client_ExecutionDetailsReceived);
         client.Event_PriceTickReceived.AttachEventHandler(client_PriceTickReceived);
         ClientWrappers = this as IWrapLongTermTradeMainForm;
      }

      private void MainForm_Load(object sender, EventArgs e)
      {
         ThreadPool.UnsafeQueueUserWorkItem(delegate
         {
            ClientWrappers.ConnectToTws();
         }, null);
      }

      private void buttonTrade_Click(object sender, EventArgs e)
      {
         if (textBoxOrderEntry.Text.Length == 0) return;
         if (!Connected)
         {
            textBoxMessages.WriteLine("Error: Cannot trade when disconnected.");
         }

         ThreadPool.UnsafeQueueUserWorkItem((object orderStringObject) =>
         {
            string autoOrderString = orderStringObject as string;
            ClientWrappers.SubmitOrdersWithClosesFromTWS(autoOrderString);
         }, textBoxOrderEntry.Text);
      }

      private void buttonDisconnect_Click(object sender, EventArgs e)
      {
         if (Connected)
         {
            ThreadPool.UnsafeQueueUserWorkItem(delegate
            {
               client.DisconnectFromTWS();
               textBoxMessages.WriteLine("Disconnected.");
               _areDisconnected = true;
            }, null);
         }
         else
         {
            textBoxMessages.WriteLine("Already disconnected.");
         }
      }

      private void buttonTest1_Click(object sender, EventArgs e)
      {
         if (!Connected) return;

         ThreadPool.UnsafeQueueUserWorkItem(delegate
         {
            Contract contract = new Future("YM", "ECBOT", "YM   JUN 09", "200906");
            MarketOrder order = new MarketOrder(ActionSide.Buy, 1);
            ClientWrappers.SubmitOrder(order, contract, OrderFlavor.None);

         }, null);
      }
   }
}
